package org.handwerkszeug.tournament.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.handwerkszeug.tournament.Game;
import org.handwerkszeug.tournament.Player;
import org.handwerkszeug.tournament.Tournament;

public class DefaultTournament implements Tournament {

	protected List<Player> allPlayers = new ArrayList<Player>();

	protected Comparator<Player> strategy;

	public DefaultTournament(Comparator<Player> strategy) {
		assert strategy != null;
		this.strategy = strategy;
	}

	@Override
	public void add(Player p) {
		assert p != null;
		this.allPlayers.add(p);
	}

	/**
	 * @see {@link #sort()}
	 */
	@Override
	public List<Game> begin() {
		assert 5 < allPlayers.size();
		List<Game> result = new ArrayList<Game>();
		Deque<Player> all = new LinkedList<Player>(sort());

		int threePlayerTable = 4 - (all.size() % 4);
		for (int i = 0; i < threePlayerTable; i++) {
			result.add(game(all, 3));
		}
		while (all.isEmpty() == false) {
			result.add(game(all, 4));
		}
		Collections.reverse(result);
		return result;
	}

	protected Game game(Deque<Player> all, int playerCount) {
		Set<Player> sp = new HashSet<Player>();
		for (int i = 0; i < playerCount; i++) {
			sp.add(all.removeLast());
		}
		return game(sp);
	}

	protected Game game(Set<Player> sp) {
		return new DefaultGame(sp);
	}

	@Override
	public void end(List<Game> list) {
		assert list != null;
		for (Game g : list) {
			g.assignMatchPoints();
		}
	}

	@Override
	public List<Player> sort() {
		Collections.sort(this.allPlayers, this.strategy);
		return Collections.unmodifiableList(this.allPlayers);
	}
}
